home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_300
/
359_11
/
patch5.000
/
EMU387_EMU.CC
< prev
next >
Wrap
C/C++ Source or Header
|
1991-09-11
|
7KB
|
288 lines
#include <stdio.h>
#include <stdlib.h>
#include "emu.h"
#include "const.h"
int modrm;
char saw[256*8];
int status_word = 0;
int control_word = 0x77e;
reg regs[8] = {
{ SIGN_POS, TW_E, 0, 0x0, 0x0 },
{ SIGN_POS, TW_E, 0, 0x0, 0x0 },
{ SIGN_POS, TW_E, 0, 0x0, 0x0 },
{ SIGN_POS, TW_E, 0, 0x0, 0x0 },
{ SIGN_POS, TW_E, 0, 0x0, 0x0 },
{ SIGN_POS, TW_E, 0, 0x0, 0x0 },
{ SIGN_POS, TW_E, 0, 0x0, 0x0 },
{ SIGN_POS, TW_E, 0, 0x0, 0x0 },
};
int top = 0;
FUNC esc_table[64] = {
emu_00, emu_10, emu_20, emu_30, emu_40, emu_50, emu_60, emu_70,
emu_01, emu_11, emu_21, emu_31, emu_41, emu_51, emu_61, emu_71,
emu_02, emu_12, emu_22, emu_32, emu_42, emu_52, emu_62, emu_72,
emu_03, emu_13, emu_23, emu_33, emu_43, emu_53, emu_63, emu_73,
emu_04, emu_14, emu_24, emu_34, emu_44, emu_54, emu_64, emu_74,
emu_05, emu_15, emu_25, emu_35, emu_45, emu_55, emu_65, emu_75,
emu_06, emu_16, emu_26, emu_36, emu_46, emu_56, emu_66, emu_76,
emu_07, emu_17, emu_27, emu_37, emu_47, emu_57, emu_67, emu_77,
};
int emu_initted = 0;
void emu_entry()
{
if (emu_initted != 0x12345678)
{
emu_initted = 0x12345678;
// eprintf(
// "Installing the 80387 Emulator. Copyright (C) 1991 DJ Delorie.\n"
// "WARNING: This is a TEST version of this emulator. If it doesn't work,\n"
// "then don't use it. Not all of the opcodes are implemented, and the\n"
// "ones that are may not work right in extreme cases. Use at your own risk.\n"
// );
}
// eprintf("eax=0x%08x ebx=0x%08x ecx=0x%08x edx=0x%08x\n", eax, ebx, ecx, edx);
// eprintf("esi=0x%08x edi=0x%08x ebp=0x%08x eip=0x%08x\n", esi, edi, ebp, eip);
if (*eip == 0x66) // operand size - we know what size we need
eip++;
if (*eip == 0x9b) // fwait
return;
// int see = ((int)(eip[0] & 7) << 8) | eip[1];
// if (saw[see] != 42)
// {
// eprintf("EMU387: %02x %02x %02x %02x - e%d%d", eip[0], eip[1], eip[2], eip[3], eip[0]&7, (eip[1]>>3)&7);
// eprintf(" s%d\n", eip[1]&7);
// saw[see] = 42;
// }
int esc_value = *eip++ & 7;
modrm = *eip++;
esc_value |= (modrm & 070);
(esc_table[esc_value])();
// emu_printall();
}
void emu_bad()
{
eprintf("Unimplemented 80387 Opcode at eip=0x%08x : %02x", eip-2, eip[-2]);
if (eip[-1] > 0277)
eprintf(" %02x", eip[-1]);
else
eprintf(" /%d", (eip[-1]>>3)&7);
eprintf(" - e%d%d", eip[-2]&7, (eip[-1]>>3)&7);
if (eip[-1] > 0277)
eprintf(" s%d", eip[-1]&7);
eprintf("\n");
exception(EX_I);
}
void emu_printall()
{
static char *tag_desc[] = { "Valid", "Zero", "Special", "Empty" };
status_word = status_word & ~SW_TOP;
status_word += (top&7) * SW_TOPS;
eprintf(" SW: 0x%04x top=%d cc=%d%d%d%d ", status_word, top&7,
status_word & SW_C3?1:0, status_word & SW_C2?1:0,
status_word & SW_C1?1:0, status_word & SW_C0?1:0);
eprintf("CW: 0x%04x\n", control_word);
for (int i=0; i<8; i++)
{
reg *r = &st(i);
switch (r->tag)
{
case TW_E:
continue;
eprintf("st(%d) ", i);
break;
case TW_Z:
eprintf("st(%d) %c .0000 0000 0000 0000 ",
i, r->sign ? '-' : '+');
break;
case TW_S:
case TW_V:
eprintf("st(%d) %c .%04x %04x %04x %04x e%+-6d ", i,
r->sign ? '-' : '+',
(long)(r->sigh >> 16),
(long)(r->sigh & 0xFFFF),
(long)(r->sigl >> 16),
(long)(r->sigl & 0xFFFF),
r->exp - EXP_BIAS + 1);
}
eprintf("%s\n", tag_desc[r->tag]);
}
fflush(stderr);
}
static struct {
int type;
char *name;
} ex_names[] = {
EX_SO, "stack overflow",
EX_SU, "stack underflow",
EX_P, "loss of precision",
EX_U, "underflow",
EX_O, "overflow",
EX_Z, "divide by zero",
EX_D, "denormalized operand",
EX_I, "invalid operation",
0,0
};
void exception(int n)
{
int i;
status_word |= n;
if (n == EX_SU)
status_word &= ~SW_C1;
for (i=0; ex_names[i].type; i++)
if (ex_names[i].type == n)
break;
if (ex_names[i].type)
eprintf("80387 Exception: %s!\n", ex_names[i].name);
else
eprintf("80387 Exception: 0x%04x!\n", n);
if (~control_word & n & CW_EXM)
{
emu_printall();
asm("movl $0x4cff,%eax");
asm("int $0x21");
}
}
void setcc(int cc)
{
status_word &= ~(SW_C0|SW_C1|SW_C2|SW_C3);
status_word |= cc & (SW_C0|SW_C1|SW_C2|SW_C3);
}
int full()
{
if (st(7).tag != TW_E)
{
exception(EX_SO);
top--;
r_mov(CONST_NAN, st(0));
return 1;
}
return 0;
}
int empty(int i)
{
if (st(i).tag == TW_E)
{
exception(EX_SU);
return 1;
}
return 0;
}
static int sregval(int reg, int mod)
{
switch (reg)
{
case 0: return eax;
case 1: return ecx;
case 2: return edx;
case 3: return ebx;
case 4: return (mod==-1) ? 0 : esp;
case 5: return mod ? ebp : 0; // data
case 6: return esi;
case 7: return edi;
}
}
static int scale[] = { 1, 2, 4, 8 };
static int getsib()
{
int mod = modrm >> 6;
int sib = *eip++;
int ss = sib>>6;
int index = (sib>>3) & 7;
int base = sib & 7;
int rv = sregval(base, mod) + sregval(index, -1) * scale[ss];
int rv2;
switch (mod)
{
case 1:
rv2 = *(signed char *)eip++;
rv += rv2;
break;
case 0:
if (base != 5)
break;
case 2:
((unsigned char *)&rv2)[0] = *eip++;
((unsigned char *)&rv2)[1] = *eip++;
((unsigned char *)&rv2)[2] = *eip++;
((unsigned char *)&rv2)[3] = *eip++;
rv += rv2;
break;
}
return rv;
}
static int regval(int reg, int mod)
{
switch (reg)
{
case 0: return eax;
case 1: return ecx;
case 2: return edx;
case 3: return ebx;
case 4: return getsib();
case 5: return mod ? ebp : 0; // data
case 6: return esi;
case 7: return edi;
}
}
void *get_modrm()
{
int mod = modrm>>6;
int rm = modrm & 7;
int rv;
switch (mod)
{
case 0:
if (rm == 5)
{
((unsigned char *)&rv)[0] = *eip++;
((unsigned char *)&rv)[1] = *eip++;
((unsigned char *)&rv)[2] = *eip++;
((unsigned char *)&rv)[3] = *eip++;
}
else
rv = regval(rm, mod);
break;
case 1:
if (rm != 4)
rv = (*(signed char *)eip++) + regval(rm, mod);
else
rv = regval(rm, mod);
break;
case 2:
if (rm != 4)
{
((unsigned char *)&rv)[0] = *eip++;
((unsigned char *)&rv)[1] = *eip++;
((unsigned char *)&rv)[2] = *eip++;
((unsigned char *)&rv)[3] = *eip++;
rv += regval(rm, mod);
}
else
rv = regval(rm, mod);
break;
case 3:
eprintf("Attempt to get address from mod = 3\n");
exit(1);
}
// eprintf("modrm returning 0x%x\n", rv);
return (void *)rv;
}